package com.bitcola.security.me.biz;

import com.bitcola.entity.*;
import com.bitcola.security.auth.common.util.EncoderUtil;
import com.bitcola.security.common.biz.BaseBiz;
import com.bitcola.security.common.context.BaseContextHandler;
import com.bitcola.security.common.msg.ColaChainBalance;
import com.bitcola.security.common.util.MD5Utils;
import com.bitcola.security.common.util.Snowflake;
import com.bitcola.security.common.util.TimeUtils;
import com.bitcola.security.me.constant.WithdrawInConstant;
import com.bitcola.security.me.feign.IChainServiceFeign;
import com.bitcola.security.me.feign.IConfigFeign;
import com.bitcola.security.me.feign.IDataServiceFeign;
import com.bitcola.security.me.feign.IPushFeign;
import com.bitcola.security.me.mapper.BalanceChangeLogMapper;
import com.bitcola.security.me.mapper.ColaFinancialRecordsMapper;
import com.bitcola.security.me.mapper.ColaMeBalanceMapper;
import com.bitcola.security.me.util.DateUtil;
import com.bitcola.security.me.util.OrderIdUtil;
import com.bitcola.security.me.vo.InWithdrawDetail;
import com.bitcola.security.me.vo.InWithdrawListVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import com.bitcola.security.me.mapper.ColaMeBalanceWithdrawinMapper;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * 用户提现记录
 *
 * @author Mr.AG
 * @email 463540703@qq.com
 * @date 2018-08-01 09:03:16
 */
@Service
public class ColaMeBalanceWithdrawinBiz extends BaseBiz<ColaMeBalanceWithdrawinMapper, ColaMeBalanceWithdrawin> {

    @Autowired
    ColaMeBalanceWithdrawinMapper mapper;

    @Autowired
    ColaCoinBiz coinBiz;

    @Autowired
    ColaMeBalanceBiz userBalanceBiz;

    @Autowired
    ColaMeBalanceMapper balanceMapper;

    @Autowired
    ColaUserBiz userBiz;

    @Autowired
    ColaCoinBiz colaCoinBiz;

    @Autowired
    ColaFinancialRecordsMapper financialRecordsMapper;

    @Resource
    IPushFeign pushFeign;

    @Autowired
    OrderIdUtil orderIdUtil;

    @Resource
    IChainServiceFeign chainServiceFeign;

    @Resource
    IDataServiceFeign dataServiceFeign;

    @Resource
    IConfigFeign configFeign;

    @Autowired
    ColaMeBalanceWithdrawinBiz biz;

    @Autowired
    RedisTemplate<String, String> redisTemplate;
    @Autowired
    BalanceChangeLogMapper balanceChangeLogMapper;
    Snowflake snowflake=new Snowflake();
    /**
     * 冲提记录
     *
     * @param coinCode
     * @param timestamp
     * @param keyWord
     * @return
     */
    public List<InWithdrawListVo> list(String coinCode, Long timestamp, Integer size, String keyWord, Long startTime, Long endTime, String type) {
        List<InWithdrawListVo> voList = new ArrayList<>();
        List<ColaCoin> coins = new ArrayList<>();
        if (StringUtils.isEmpty(coinCode)) {
            coins = colaCoinBiz.selectListAll();
        } else {
            coins.add(colaCoinBiz.getByCoinCode(coinCode));
        }
        for (ColaCoin coin : coins) {
            List<ColaMeBalanceWithdrawin> list = mapper.list(coin.getCoinCode(), BaseContextHandler.getUserID(), timestamp, size, keyWord, startTime, endTime, type);
            for (ColaMeBalanceWithdrawin balance : list) {
                InWithdrawListVo vo = new InWithdrawListVo();
                vo.setId(balance.getId());
                vo.setCoinCode(balance.getCoinCode());
                vo.setTime(balance.getDate());
                vo.setNumber(balance.getNumber());
                if (WithdrawInConstant.TYPE_IN.equalsIgnoreCase(balance.getType())) {
                    vo.setConfirmation(balance.getConfirmations().toString() + "/" + balance.getConfirmationNumber());
                }
                vo.setTxId(balance.getTxId());
                vo.setStatus(balance.getStatus());
                vo.setType(balance.getType());
                vo.setIcon(balance.getIcon());
                vo.setScale(coin.getPrec());
                voList.add(vo);
        }

        }

        if(voList.size()>size){
            voList.sort((v1,v2)-> v2.getTime().compareTo(v1.getTime()));
            voList=voList.subList(0,size-1);

        }
        return voList;
    }


    /**
     * 获取用户当日提现额度
     *
     * @param userID
     * @param coinCode
     * @return
     */
    public BigDecimal getTodayNumber(String userID, String coinCode) {
        return mapper.getTodayNumber(userID, coinCode, DateUtil.getTodyTime());
    }

    /**
     * 获取当日提现次数
     *
     * @param userID
     * @return
     */
    public int getTodayTime(String userID) {
        return mapper.getTodayTime(userID, DateUtil.getTodyTime());
    }

    /**
     * 提现信息
     *
     * @param coinCode
     * @param userID
     * @return
     */
    public Map<String, Object> withdrawInfo(String coinCode, String userID) {
        ColaUserEntity info = userBiz.info(BaseContextHandler.getUserID());
        String telPhone = info.getTelPhone();

        Map<String, Object> map = new HashMap<>();
        ColaCoin coin = coinBiz.getByCoinCode(coinCode);
        map.put("withdrawOne", coin.getWithdrawOne());
        map.put("withdrawAmount", coin.getWithdrawAmount());
        map.put("feesFlat", coin.getFeesFlat());
        map.put("feesPercent", coin.getFeesPercent());
        map.put("minWithdrawNumber", coin.getMinWithdrawNumber());
        BigDecimal number = userBalanceBiz.getCoinNumber(userID, coinCode);
        map.put("balanceAvailable", number.setScale(coin.getPrec(), RoundingMode.DOWN));
        map.put("dailyLimitNumber", info.getWithdrawTime());
        map.put("pinSet", StringUtils.isNotBlank(info.getMoneyPassword()));
        if (StringUtils.isBlank(telPhone)) {
            map.put("mode", "EmailCode");
        } else {
            map.put("mode", "SMSCode");
        }
        return map;
    }


    public InWithdrawDetail detail(String orderId) {
        InWithdrawDetail detail = mapper.detail(orderId);
        if (StringUtils.isNotBlank(detail.getTxId())) {
            detail.setTxId(detail.getTxId().split("@")[0]);
        }
        BigDecimal worth = colaCoinBiz.getCoinWorth(detail.getCoinCode()).multiply(detail.getNumber());
        detail.setWorth(worth);
        return detail;
    }

    /**
     * 提币申请
     *
     * @param userID
     * @param coinCode
     * @param id
     */
    @Transactional
    public void withdrawApply(String userID, String coinCode, String address, BigDecimal number, ColaCoin coin, String note, String reason, String id,String belong) {
        perWithdraw(userID, coinCode, address, number, coin, note, reason, WithdrawInConstant.STATUS_CHECKING, id, belong);
    }


    @Transactional
     void perWithdraw(String userID, String coinCode, String address, BigDecimal number, ColaCoin coin, String note, String reason, String status, String id,String belong) {
        //扣除手续费
        BigDecimal feesFlat = coin.getFeesFlat();
        BigDecimal feesPercent = coin.getFeesPercent();

        BigDecimal fee = feesFlat;
        if (feesPercent.compareTo(BigDecimal.ZERO) != 0) {
            fee = fee.add(number.multiply(feesPercent));
        }
        belong=ColaMeBalanceBiz.belongMap(belong);
        BigDecimal realNumber = number.subtract(fee);
        ColaMeBalanceWithdrawin entity = new ColaMeBalanceWithdrawin();
        entity.setAddress(address);
        entity.setId(id);
        entity.setUserId(userID);
        entity.setCoinCode(coinCode);
        entity.setDate(System.currentTimeMillis());
        entity.setIcon(coin.getIcon());
        entity.setNote(note);
        entity.setNumber(number);
        entity.setType(WithdrawInConstant.TYPE_WITHDRAW);
        entity.setRealNumber(realNumber);
        entity.setStatus(status);
        entity.setReason(reason);
        entity.setChainType(belong);
        entity.setFees(fee);
        entity.setSign(MD5Utils.MD5(EncoderUtil.WITHDRAW_KEY + id + userID + status + number.setScale(0, RoundingMode.DOWN)));
        int i = mapper.perWithdraw(userID, number, coinCode, EncoderUtil.BALANCE_KEY);
        if (i == 1) {
            mapper.insert(entity);
            BalanceChange balanceChange=new BalanceChange();
            balanceChange.setId(snowflake.nextIdStr());
            balanceChange.setAmount(number.negate());
            balanceChange.setCoinCode(coinCode);
            balanceChange.setCreateTime(new Date());
            balanceChange.setDescription(id);
            balanceChange.setType("withdraw");
            balanceChange.setUserId(userID);
            balanceChangeLogMapper.insert(balanceChange);
        }


    }


    public WithdrawResponse checkBalance(String coinCode, BigDecimal number) {
        WithdrawResponse response = new WithdrawResponse();
        String userID = BaseContextHandler.getUserID();
        Integer unNormal = 0;
        if (unNormal == 0) {
            List <Map<String,Object>> deposits = mapper.selectDepositSum(BaseContextHandler.getUserID());
            List <Map<String,Object>> withdraws = mapper.selectDepositSum(BaseContextHandler.getUserID());

            BigDecimal deposit = BigDecimal.ZERO;// 充值总额
            BigDecimal withdraw = BigDecimal.ZERO; // 提币总额

            deposit = getBigDecimal(deposits, deposit);
            withdraw = getBigDecimal(withdraws, withdraw);

            BigDecimal total = coinBiz.getCoinWorth(coinCode).multiply(number);
            if (BigDecimal.ZERO.compareTo(deposit) == 0) {
                if (total.add(withdraw).compareTo(new BigDecimal(10)) > 0) {
                    response.setChecked(false);
                    response.setReason("没有充值,提币超过100美元");
                    return response;
                }
            } else {
                String config = configFeign.getConfig("cola_withdraw_deposit_rate");
                int i = withdraw.add(total).divide(deposit, 10, RoundingMode.HALF_UP).compareTo(new BigDecimal(config));

                if (i > 0) {
                    response.setChecked(false);
                    response.setReason("提币数量超过充值数量" + config + "倍");
                    return response;
                }
            }
//            ColaChainBalance balance = mapper.getChainBalanceByCoinCode(coinCode);
//            if (number.add(balance.getFeeLimit()).compareTo(balance.getBalance()) > 0 || balance.getFeeLimit().compareTo(balance.getFeeBalance()) > 0){
//                response.setChecked(false);
//                response.setReason(coinCode+" 资金或者燃料费不足,当前资金:"+balance.getBalance().stripTrailingZeros().toPlainString()+
//                        " 燃料费:"+balance.getFeeBalance().stripTrailingZeros().toPlainString());
//                return response;
//            }
//            balance.setBalance(balance.getBalance().subtract(number));
//            mapper.updateChainBalanceById(balance);
            response.setChecked(true);
        } else {
            response.setChecked(false);
            response.setReason("资金签名出错");
        }
        response.setReason("全部人工审核");

        return response;
    }

    private BigDecimal getBigDecimal(List<Map<String, Object>> withdraws, BigDecimal withdraw) {
        for (Map<String, Object> map : withdraws) {
            String coin = map.get("coin").toString();
            BigDecimal account = new BigDecimal(map.get("amount").toString());
            BigDecimal worth = coinBiz.getCoinWorth(coin);
            withdraw = withdraw.add(account.multiply(worth));
        }
        return withdraw;
    }

    public String withdraw(String id, String coinCode) {
        mapper.checkSuccess(id, WithdrawInConstant.STATUS_WITHDRAW, EncoderUtil.WITHDRAW_KEY);
        return "可以了";
    }

    private static final String GET_CHAIN_BALANCE_LIMIT = "GET_CHAIN_BALANCE_LIMIT";

    /**
     * 获取区块链余额
     */
    @Scheduled(cron = "0 0 */1 * * ?")
    public void getChainBalance() {
        String key = GET_CHAIN_BALANCE_LIMIT + TimeUtils.getDateFormat(System.currentTimeMillis());
        Boolean requestTag = redisTemplate.opsForValue().setIfAbsent(key, "1");
        if (requestTag) {
            try {
                List<ColaChainBalance> allChainBalance = mapper.getAllChainBalance();
                for (ColaChainBalance balance : allChainBalance) {
                    getChainBalance(balance);
                }
                Thread.sleep(60 * 1000);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                redisTemplate.delete(key);
            }
        }
    }

    public void getChainBalance(ColaChainBalance balance) {
        ColaChainBalance response = chainServiceFeign.getChainBalance(balance.getModule(), balance.getCoinCode(), balance.getFeeCoinCode());
        mapper.updateChainBalanceById(response);
    }


}